// ============================================================================
//
// LCP-net framework by Pierre CHATEL chatelp@gmail.com
// Distributed under GPLv3
// Copyright (C) THALES Land & Joint Systems, 2008, 2009. All rights reserved
//
// ============================================================================

/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package com.thalesgroup.preferenceFramework.models.LCPnet.impl;

import java.util.Iterator;
import java.util.logging.Logger;

import org.eclipse.emf.ecore.EClass;

import com.thalesgroup.graphFramework.core.Graph;
import com.thalesgroup.graphFramework.core.Vertex;
import com.thalesgroup.preferenceFramework.algorithms.DepthBasedWeights;
import com.thalesgroup.preferenceFramework.models.LCPnet.COutcome;
import com.thalesgroup.preferenceFramework.models.LCPnet.LCPnet;
import com.thalesgroup.preferenceFramework.models.LCPnet.LCPnetPackage;
import com.thalesgroup.preferenceFramework.models.LCPnet.LNode;
import com.thalesgroup.preferenceFramework.models.LCPnet.LTwoTuple;
import com.thalesgroup.preferenceFramework.models.LCPnet.exceptions.LCPnetEvaluationException;
import com.thalesgroup.preferenceFramework.models.LCPnet.exceptions.LNodeEvaluationException;
import com.thalesgroup.preferenceFramework.models.impl.OutcomeImpl;

/**
 * <!-- begin-user-doc --> An implementation of the model object '
 * <em><b>COutcome</b></em>'. <!-- end-user-doc -->
 * <p>
 * </p>
 *
 * @generated
 */
public class COutcomeImpl extends OutcomeImpl implements COutcome {
	
	private double utility = -1;
	
	private static Logger logger = Logger.getLogger(COutcomeImpl.class.getName());

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	protected COutcomeImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return LCPnetPackage.Literals.COUTCOME;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	public LTwoTuple getLinguisticUtility() throws LCPnetEvaluationException {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	public double compareTo(COutcome anotherOutcome) throws LCPnetEvaluationException {
		double thisUtility = this.getUtility();
		double otherUtility = anotherOutcome.getUtility();
		
		return thisUtility - otherUtility;
	}

	public double getUtility() throws LCPnetEvaluationException {
		//if utility < 0, it hasn't been computed before
		if(utility < 0) {
			utility = 0;
			
			//1 - Convert preference network to finalized graph
			LCPnet net = (LCPnet) this.getPreferenceNetwork();
			Graph<LNode, Void> graph = net.getFinalizedGraph(this);
		
			//2 - Run weights calculation algorithm on finalized graph
			DepthBasedWeights.run(graph);

			//3 - Compute global utility
			for(Iterator<Vertex<LNode, Void>> iv=graph.getVertices(); iv.hasNext();) {
				Vertex<LNode, Void> vertex=iv.next();
				
				// 3.a - compute local node utility using fuzzy inference
				LNode lnode = vertex.getVertex();
				double localUtility = 0.5;
				try {
					localUtility = lnode.getUtility(this);
				} catch (LNodeEvaluationException e) {
					//Implementation choice: if error during node evaluation, node utility = 0.5
					logger.warning("Error during node " + lnode.getName() + " evaluation, node utility fixed to 0.5");
				}
				
				// 3.b - retrieve local node weight
				Double localWeight = (Double) vertex.getUserFeature(DepthBasedWeights.weightKey);
				
				// 3.c - add local factor to global utility
				utility += (localUtility * localWeight);			
			}
		}

		return utility;
	}

} // COutcomeImpl
